import sys
import os

file_path = os.path.abspath(__file__)
end = file_path.index('qmt_auto_trade') + 17
project_path = file_path[0:end]
sys.path.append(project_path)

import mk_common.component.qmt.qmt_trade_api as qmt_trade_api

import push.push_msg_service as push_msg_service
import config.config_service as config_service
import math
from datetime import datetime

import mk_common.util.data_frame_util as data_frame_util
from loguru import logger
from qmt_enum.operate_enum import OperateEnum
from functools import lru_cache
import strategy.db_util as db_util
import mk_common.component.cache.cache_service as cache_service

LOG_HAD_BUY = 'had_buy'

LOG_HAD_POSITION = 'had_position'


# 计算买入量
def calculate_buy_volume(buy_price, strategy_trade_money):
    buy_volume = math.floor((strategy_trade_money / (buy_price * 100)))
    return buy_volume * 100


# 检查当前持仓
def check_now_day_position(str_day, symbol):
    position_df = position_query_api(str_day)
    if data_frame_util.is_empty(position_df):
        return False
    one_position_df = position_df.loc[position_df['stock_code'] == symbol]
    if data_frame_util.is_empty(one_position_df):
        return False
    else:
        return True
    contains_symbol = position_df['stock_code'].isin([symbol]).any()
    if contains_symbol:
        return True
    else:
        return False


# 下单买入
def order_buy(symbol, now_price):
    now_date = datetime.now()
    str_day = now_date.strftime('%Y-%m-%d')

    if db_util.query_today_trade(symbol, str_day):
        id_key = symbol + symbol + LOG_HAD_BUY
        result_buy = cache_service.get_cache(id_key)
        if result_buy is None:
            logger.warning("当天已经买入过:{}", symbol)
            cache_service.set_cache(id_key, LOG_HAD_BUY)
        return '当天已经买入过'
    elif check_now_day_position(str_day, symbol):
        id_key = symbol + symbol + LOG_HAD_POSITION
        result_position = cache_service.get_cache(id_key)
        if result_position is None:
            logger.warning("当前持仓股票已经包含此股票:{}", symbol)
            cache_service.set_cache(id_key, LOG_HAD_POSITION)
        return '当前持仓股票已经包含此股票'
    else:
        config_info_dict = config_service.get_config_info()
        qmt_account_no = config_info_dict.get('qmt_account_no')
        qmt_data_path = config_info_dict.get('qmt_data_path')
        max_buy_chg_float = config_info_dict.get('max_buy_chg_float')
        strategy_trade_money = config_info_dict.get('strategy_trade_money')
        buy_price = round(now_price * (1 + max_buy_chg_float), 2)
        buy_volume = calculate_buy_volume(buy_price, strategy_trade_money)
        try:
            trade_result = qmt_trade_api.order_buy(symbol, buy_price, buy_volume, qmt_account_no, qmt_data_path)
            entrust_no = trade_result.get('entrust_no')
            if int(entrust_no) == -1:
                title = "委托失败"
                msg = "委托失败，请检查客户端是否正常:" + symbol
                push_msg_service.push_msg(title, msg)
                return False
            operate_code = OperateEnum.BUY.operate_code

            db_util.insert_trade_data(now_date, symbol,
                                      operate_code, buy_price,
                                      buy_volume, entrust_no)

            title = "委托成功"
            msg = "委托成功，请注意交易是否成功:" + symbol
            push_msg_service.push_msg(title, msg)

            return True

        except BaseException as e:
            logger.error("委托买入失败:{},{}", symbol, str(e))
            return False


# 下单卖出
def order_sell(symbol, now_price, sell_volume):
    now_date = datetime.now()
    config_info_dict = config_service.get_config_info()
    qmt_account_no = config_info_dict.get('qmt_account_no')
    qmt_data_path = config_info_dict.get('qmt_data_path')
    max_buy_chg_float = config_info_dict.get('max_buy_chg_float')
    sell_price = round(now_price * (1 - max_buy_chg_float), 2)

    try:
        trade_result = qmt_trade_api.order_sell(symbol, sell_price, sell_volume, qmt_account_no, qmt_data_path)
        entrust_no = trade_result.get('entrust_no')

        operate_code = OperateEnum.SELL.operate_code

        db_util.insert_trade_data(now_date, symbol,
                                  operate_code, sell_price,
                                  sell_volume, entrust_no)
        return True
    except BaseException as e:
        logger.error("委托卖出失败:{},{}", symbol, str(e))
        return False


def order_cancel(entrust_no, symbol):
    config_info_dict = config_service.get_config_info()
    qmt_account_no = config_info_dict.get('qmt_account_no')
    qmt_data_path = config_info_dict.get('qmt_data_path')
    qmt_trade_api.order_cancel(entrust_no, symbol, qmt_data_path, qmt_account_no)


# 同步持仓
def sync_self_position():
    config_info_dict = config_service.get_config_info()
    qmt_account_no = config_info_dict.get('qmt_account_no')
    qmt_data_path = config_info_dict.get('qmt_data_path')
    position_df = qmt_trade_api.get_position(qmt_data_path, str(qmt_account_no))
    if data_frame_util.is_not_empty(position_df):
        self_position_table_name = config_info_dict.get('self_position')
        db_util.insert_self_position(self_position_table_name, position_df)


# str_day 每天的持仓不一样
@lru_cache(maxsize=None)
def position_query_api(str_day):
    config_info_dict = config_service.get_config_info()
    qmt_account_no = config_info_dict.get('qmt_account_no')
    qmt_data_path = config_info_dict.get('qmt_data_path')
    position_df = qmt_trade_api.get_position(qmt_data_path, str(qmt_account_no))
    return position_df


if __name__ == '__main__':
    order_sell('000001', '平安银行', 12.91, 1000)
